#ifndef __LSV_BITMAP_BITMAP_INTERNAL_H_
#define __LSV_BITMAP_BITMAP_INTERNAL_H_

//#define CACHE_NEW

#define SAVE_HEADER_LEVEL_META      1
#define SAVE_HEADER_LEVEL_CHUNKS    2
#define SAVE_HEADER_LEVEL_ALL       3

typedef struct aio_list_entry {
        struct list_head hook;
        lsv_volume_io_t vio;
        lsv_lock_t lock;
        lsv_bitmap_cache_unit_t * cache_unit;
        struct timeval tim;
} aio_list_entry_t;

int private bitmap_header_load(struct lsv_bitmap_context *bitmap_context, uint32_t first_chunk_id);
int private bitmap_header_load_async(struct lsv_bitmap_context *bitmap_root, uint32_t first_chunk_id);
int private bitmap_header_load_internal(struct lsv_bitmap_context *bitmap_context, uint32_t first_chunk_id);

int private bitmap_header_save(struct lsv_bitmap_context *bitmap_context, uint32_t level);
int lsv_bitmap_create_node(void *volume_context, struct lsv_bitmap_context **bitmap_context, uint8_t is_root, uint32_t type);
void lsv_bitmap_free_single_node(struct lsv_bitmap_context *node);
void lsv_bitmap_free_node(struct lsv_bitmap_context *node);
int lsv_bitmap_create_snapshot_internal(void * volume_context, struct lsv_bitmap_context *parent_node, const char *snap_name, uint8_t type, struct lsv_bitmap_context **new_node);
struct lsv_bitmap_context * lsv_bitmap_get_root(struct lsv_bitmap_context *node);

int private lsv_read_bitmap_node(struct lsv_bitmap_context *bitmap_context, uint32_t vvol_id, uint64_t chunk_id, uint32_t chunk_off, uint32_t len, void *bitmap_buf);
int private lsv_release_bitmap_node(struct lsv_bitmap_context *bitmap_context, uint32_t vvol_id, uint64_t chunk_id, uint32_t chunk_off, uint32_t len);

int private lsv_write_bitmap_node(void *volume_context, struct lsv_bitmap_context *bitmap_context,
        uint32_t chunk_id, uint32_t chunk_off, uint32_t len, void *bitmap_buf, int flags);
        
int private lsv_bitmap_paged_read_node(struct lsv_bitmap_context *bitmap_context, uint64_t off, struct lsv_bitmap_unit *bitmap_buf);

int private lsv_bitmap_paged_write_node(void *volume_context, struct lsv_bitmap_context *bitmap_context,
                                        uint64_t off, struct lsv_bitmap_unit *bitmap_buf, int flags);

int private lsv_bitmap_paged_read_node_directly(struct lsv_bitmap_context *bitmap_context, uint64_t off, struct lsv_bitmap_unit *bitmap_buf);

struct lsv_bitmap_context * lsv_bitmap_get_by_name(struct lsv_bitmap_context *node, const char * name);
int lsv_bitmap_revert_snapshot_internal(void * volume_context, struct lsv_bitmap_context * new_parent);
int lsv_bitmap_delete_snapshot_internal(struct lsv_bitmap_context *bitmap_context);
int lsv_bitmap_has_snapshot(void * volume_context);
struct lsv_bitmap_context * lsv_bitmap_volume_to_node(void * volume_context); 
int lsv_bitmap_protect_node(struct lsv_bitmap_context * node, int protect);  
struct lsv_bitmap_context * lsv_bitmap_get_parent_volume(struct lsv_bitmap_context *node); 
struct lsv_bitmap_context * lsv_bitmap_get_current_volume(struct lsv_bitmap_context *node); 
struct lsv_bitmap_context * lsv_bitmap_get_root_node(void * volume_context); 

int lsv_bitmap_is_row2(void *volume_context);

int lsv_bitmap_alloc_chunk(void *volume_context, uint32_t *chunk_id, int zero);
int lsv_bitmap_read_chunk(void *volume_context, uint32_t vvol_id, uint32_t chunk_id, uint32_t chunk_off, uint32_t len, void *buf);
int lsv_bitmap_write_chunk(void *volume_context, uint32_t chunk_id, uint32_t chunk_off, uint32_t len, void *buf);
int lsv_bitmap_write_chunk_async(void *volume_context, void *buf, lsv_volume_io_t * io, void * param);
int lsv_bitmap_read_chunk_async(void *volume_context, void *buf, lsv_volume_io_t *io, void *param);
int lsv_bitmap_free_chunk(void *volume_context, uint32_t chunk_id);

int lsv_bitmap_write_data(void *volume_context, uint32_t chunk_id, uint32_t chunk_off, uint32_t len, void *buf);

void lsv_bitmap_init_lock(lsv_bitmap_context_t *node);
void lsv_bitmap_free_lock(lsv_bitmap_context_t *node);
void lsv_bitmap_lock_node(lsv_bitmap_context_t *node);
void lsv_bitmap_unlock_node(lsv_bitmap_context_t *node);

int lsv_bitmap_cache_init(struct lsv_bitmap_context * node);
uint8_t * lsv_bitmap_cache_get(struct lsv_bitmap_context * node, uint32_t vvol_id, uint32_t chunk_id, uint32_t page_off, uint32_t page_len, int load_all, lsv_bitmap_cache_unit_t **ref);
void lsv_bitmap_cache_pre_load(struct lsv_bitmap_context * node, uint32_t vvol_id, uint32_t chunk_id, uint32_t page_off, uint32_t page_len);

void lsv_bitmap_cache_unlock(lsv_bitmap_cache_unit_t *unit);
int lsv_bitmap_cache_free(struct lsv_bitmap_context * node);

int bitmap_header_read(struct lsv_bitmap_context *bitmap_context, uint64_t off, uint32_t len, void * buffer);

int volume_proto_remote_read_chunk(lsv_volume_proto_t *lsv_info, uint64_t volume_id, uint64_t chunk_id, uint32_t chunk_off, uint32_t size, void *buffer);

void lsv_bitmap_cache_mark_dirty(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

void lsv_bitmap_cache_clear_dirty(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

void lsv_bitmap_cache_mark_valid(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

void lsv_bitmap_cache_clear_valid(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

void lsv_bitmap_cache_page_unlock(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

void lsv_bitmap_cache_mark_load(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

void lsv_bitmap_cache_clear_load(lsv_bitmap_cache_unit_t * cache, uint32_t page_idx, uint32_t n_pages);

int lsv_bitmap_cache_release(struct lsv_bitmap_context * node);

int lsv_is_bitmap_cache_dirty(lsv_bitmap_cache_unit_t * cache);

int lsv_bitmap_commit_dirty_node(struct lsv_bitmap_context * node);

uint32_t lsv_bitmap_snap_get_max_id(void * volume_context);

#endif
